

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="叶飞">
  <meta name="keywords" content="">
  
    <meta name="description" content="索引  1. 索引是什么？ ​	索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)，它们包含着对数据表里所有记录的引用指针。 ​	索引是一种数据结构。数据库索引，是数据库管理系统中一个排序的数据结构，以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。更通俗的说，索引就相当于目录。为了方便查找书中的内容，通过对内容建立索引形成目录。而且索引是一个文件，">
<meta property="og:type" content="article">
<meta property="og:title" content="MySQL常见面试题-2">
<meta property="og:url" content="http://example.com/2022/04/05/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2/index.html">
<meta property="og:site_name" content="博客">
<meta property="og:description" content="索引  1. 索引是什么？ ​	索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)，它们包含着对数据表里所有记录的引用指针。 ​	索引是一种数据结构。数据库索引，是数据库管理系统中一个排序的数据结构，以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。更通俗的说，索引就相当于目录。为了方便查找书中的内容，通过对内容建立索引形成目录。而且索引是一个文件，">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215012443.png">
<meta property="og:image" content="http://example.com/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215023820-16491572618703.png">
<meta property="og:image" content="http://example.com/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215044332.png">
<meta property="og:image" content="http://example.com/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/java10-1562726251.gif">
<meta property="og:image" content="http://blog-img.coolsen.cn/img/java8-1562726251.gif">
<meta property="article:published_time" content="2022-04-05T08:24:29.000Z">
<meta property="article:modified_time" content="2022-04-06T11:58:52.071Z">
<meta property="article:author" content="叶飞">
<meta property="article:tag" content="面试">
<meta property="article:tag" content="MySQL">
<meta property="article:tag" content="数据库">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://example.com/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215012443.png">
  
  
  
  <title>MySQL常见面试题-2 - 博客</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.2","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>No Tomorrow</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="MySQL常见面试题-2"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        叶飞
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-04-05 16:24" pubdate>
          星期二, 四月 5日 2022, 4:24 下午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          <!-- compatible with older versions-->
          7.9k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          <!-- compatible with older versions-->
          66 分钟
        
      </span>
    

    
    
      
        <span id="leancloud-page-views-container" class="post-meta" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="leancloud-page-views"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">MySQL常见面试题-2</h1>
            
            
              <div class="markdown-body">
                
                <h1 id="索引"><a class="markdownIt-Anchor" href="#索引"></a> 索引</h1>
<h2 id="1-索引是什么"><a class="markdownIt-Anchor" href="#1-索引是什么"></a> 1. 索引是什么？</h2>
<p>​	索引是一种特殊的<code>文件</code>(InnoDB数据表上的索引是表空间的一个组成部分)，它们包含着对数据表里所有记录的<code>引用指针</code>。</p>
<p>​	索引是一种<code>数据结构</code>。数据库索引，是数据库管理系统中一个<code>排序的数据结构</code>，以协助快速查询、更新数据库表中数据。索引的实现通常使用<strong>B树及其变种B+树</strong>。更通俗的说，索引就相当于<code>目录</code>。为了方便查找书中的内容，通过对内容建立索引形成目录。而且索引是一个文件，它是要<code>占据物理空间</code>的。</p>
<p>​	MySQL索引的建立对于MySQL的高效运行是很重要的，索引可以大大提高MySQL的检索速度。比如我们在查字典的时候，前面都有检索的拼音和偏旁、笔画等，然后找到对应字典页码，这样然后就打开字典的页数就可以知道我们要搜索的某一个key的全部值的信息了。</p>
<h2 id="2-索引有哪些优缺点"><a class="markdownIt-Anchor" href="#2-索引有哪些优缺点"></a> 2. 索引有哪些优缺点？</h2>
<p><strong>索引的优点</strong></p>
<ul>
<li>可以大大<strong>加快数据的检索速度</strong>，这也是创建索引的最主要的原因。</li>
<li>通过使用索引，可以在查询的过程中，使用优化隐藏器，提高系统的性能。</li>
</ul>
<p><strong>索引的缺点</strong></p>
<ul>
<li>时间方面：<strong>创建索引和维护索引</strong>要耗费时间，具体地，当对表中的数据进行增加、删除和修改的时候，索引也要动态的维护，会降低增/改/删的执行效率；</li>
<li>空间方面：索引需要占<strong>物理空间</strong>。</li>
</ul>
<h2 id="3-mysql有哪几种索引类型"><a class="markdownIt-Anchor" href="#3-mysql有哪几种索引类型"></a> 3. MySQL有哪几种索引类型？</h2>
<p>1、从<strong>存储结构</strong>上来划分：BTree索引（B-Tree或B+Tree索引），Hash索引，full-index全文索引，R-Tree索引。这里所描述的是索引<strong>存储时保存的形式</strong>，</p>
<p>2、从<strong>应用层次</strong>来分：普通索引，唯一索引，复合索引。</p>
<ul>
<li>
<p>普通索引：即一个索引只包含单个列，一个表可以有多个单列索引</p>
</li>
<li>
<p>唯一索引：索引列的值必须唯一，但允许有空值</p>
</li>
<li>
<p>复合索引：多列值组成一个索引，专门用于<strong>组合搜索</strong>，其效率大于索引合并</p>
</li>
<li>
<p>⭐️聚簇索引(聚集索引)：并不是一种单独的索引类型，而是一种<u>数据存储方式</u>。具体细节取决于不同的实现，InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。</p>
</li>
<li>
<p>非聚簇索引： 不是聚簇索引，就是非聚簇索引</p>
</li>
</ul>
<p>3、根据中数据的物理顺序与键值的逻辑（索引）顺序关系： 聚集索引，非聚集索引。</p>
<h2 id="4-说一说索引的底层实现"><a class="markdownIt-Anchor" href="#4-说一说索引的底层实现"></a> 4. 说一说索引的底层实现？</h2>
<p><strong>Hash索引</strong></p>
<p>基于哈希表实现，只有精确匹配索引所有列的查询才有效，对于每一行数据，存储引擎都会对所有的索引列计算一个哈希码（hash code），并且Hash索引将所有的哈希码存储在索引中，同时在索引表中保存指向每个数据行的指针。</p>
<p><img src="/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215012443.png" srcset="/img/loading.gif" lazyload alt></p>
<p><strong>B-Tree索引</strong>（MySQL使用B+Tree）</p>
<p>B-Tree能加快数据的访问速度，因为存储引擎不再需要进行全表扫描来获取数据，数据分布在各个节点之中。</p>
<p><img src="/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215023820-16491572618703.png" srcset="/img/loading.gif" lazyload alt></p>
<p><strong>B+Tree索引</strong></p>
<p>是B-Tree的改进版本，同时也是数据库索引索引所采用的存储结构。<strong>数据都在叶子节点上</strong>，并且增加了顺序访问指针，每个叶子节点都指向<strong>相邻的叶子节点</strong>的地址【链表结构】。相比B-Tree来说，B+进行范围查找时只需要查找两个节点，进行遍历即可。而B-Tree需要获取所有节点，相比之下B+Tree效率更高。</p>
<p>B+tree性质：</p>
<ul>
<li>
<p>n棵子tree的节点包含n个关键字，不用来保存数据而是<strong>保存数据的索引</strong>。</p>
</li>
<li>
<p>所有的叶子结点中包含了全部关键字的信息，及指向含这些关键字记录的指针，且叶子结点本身依关键字的大小自小而大顺序链接。</p>
</li>
<li>
<p>所有的<strong>非终端/叶子结点</strong>可以看成是索引部分，结点中仅含其子树中的最大（或最小）关键字。</p>
</li>
<li>
<p>B+ 树中，数据对象的插入和删除仅在叶节点上进行。</p>
</li>
<li>
<p>B+树有2个头指针，一个是树的根节点，一个是最小关键码的叶节点。</p>
</li>
</ul>
<p><img src="/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/image-20210411215044332.png" srcset="/img/loading.gif" lazyload alt></p>
<h2 id="5-为什么索引结构默认使用btree而不是b-treehash二叉树红黑树"><a class="markdownIt-Anchor" href="#5-为什么索引结构默认使用btree而不是b-treehash二叉树红黑树"></a> 5. 为什么索引结构默认使用B+Tree，而不是B-Tree，Hash，二叉树，红黑树？</h2>
<p>B-tree： 从两个方面来回答</p>
<ul>
<li>B+树的磁盘读写代价更低：B+树的内部节点并没有指向关键字具体信息的指针，因此其<strong>内部节点/非叶子节点</strong>相对B(B-)树更小，如果把所有同一内部节点的关键字存放在同一盘块中，那么盘块所能容纳的关键字数量也越多，一次性读入内存的需要查找的关键字也就越多，相对<code>IO读写次数就降低</code>了。</li>
<li>由于B+树的<strong>数据都存储在叶子结点</strong>中，分支结点均为索引，方便扫库，只需要扫一遍叶子结点即可，但是B树因为其分支结点同样存储着数据，我们要找到具体的数据，需要进行一次中序遍历按序来扫，所以B+树更加适合在<code>区间查询</code>的情况，所以通常B+树用于数据库索引。
<ul>
<li>遍历到叶子结点，而叶子结点之间存在链接，所以遍历叶子结点狠方便</li>
</ul>
</li>
</ul>
<p>Hash：</p>
<ul>
<li>虽然可以快速定位，但是<strong>没有顺序</strong>，IO复杂度高；</li>
</ul>
<ul>
<li>
<p>基于Hash表实现，只有Memory存储引擎显式支持哈希索引 ；</p>
</li>
<li>
<p>适合<strong>等值查询</strong>，如=、in()、&lt;=&gt;，<strong>不支持范围查询</strong> ；</p>
</li>
<li>
<p>因为不是按照索引值顺序存储的，就不能像B+Tree索引一样利用索引完成<a href>排序</a> ；</p>
</li>
<li>
<p>Hash索引在查询等值时非常快 ；</p>
</li>
<li>
<p>因为Hash索引始终索引的<strong>所有列的全部内容</strong>，所以不支持部分索引列的匹配查找 ；</p>
</li>
<li>
<p>如果有大量重复键值的情况下，哈希索引的效率会很低，因为存在<strong>哈希碰撞</strong>问题 。</p>
</li>
</ul>
<p>二叉树： 树的高度不均匀，不能自平衡，查找效率跟数据有关（树的高度），并且IO代价高。</p>
<p>红黑树： 树的<strong>高度随着数据量增加而增加</strong>，IO代价高。</p>
<h2 id="️6-讲一讲聚簇索引与非聚簇索引"><a class="markdownIt-Anchor" href="#️6-讲一讲聚簇索引与非聚簇索引"></a> ⭐️6. 讲一讲聚簇索引与非聚簇索引？</h2>
<p>​	在 InnoDB 里，索引 B+ Tree 的叶子节点存储了整行数据的是主键索引，也被称之为<strong>聚簇索引</strong>，即<strong>将数据存储与索引放到了一块</strong>，找到索引也就找到了数据。</p>
<blockquote>
<p>聚簇索引：数据和索引放到一起</p>
</blockquote>
<p>​	而索引B+ Tree的叶子节点<strong>存储了主键的值</strong>的是非主键索引，也被称之为非聚簇索引、<strong>二级索引</strong>。</p>
<p><strong>聚簇索引与非聚簇索引的区别</strong>：</p>
<ul>
<li>
<p>非聚集索引与聚集索引的区别在于非聚集索引的叶子节点不存储表中的数据，而是存储该列对应的主键（行号）</p>
</li>
<li>
<p>对于InnoDB来说，想要查找数据我们还需要根据主键再去聚集索引中进行查找，这个再根据聚集索引查找数据的过程，我们称为<strong>回表</strong>。第一次索引一般是顺序IO，回表的操作属于随机IO。需要回表的次数越多，即随机IO次数越多，我们就越倾向于使用全表扫描 。</p>
</li>
<li>
<p>通常情况下， 主键索引（聚簇索引）查询只会查一次，而非主键索引（非聚簇索引）需要回表查询多次。当然，如果是覆盖索引的话，查一次即可</p>
</li>
<li>
<p>注意：MyISAM无论主键索引还是二级索引都是非聚簇索引，而InnoDB的主键索引是聚簇索引，二级索引是非聚簇索引。我们自己建的索引基本都是非聚簇索引。</p>
</li>
</ul>
<h2 id="7-非聚簇索引一定会回表查询吗"><a class="markdownIt-Anchor" href="#7-非聚簇索引一定会回表查询吗"></a> 7. 非聚簇索引一定会回表查询吗？</h2>
<p>​	不一定，这涉及到查询语句所要求的字段是否全部命中了索引，<strong>如果全部命中了索引，那么就不必再进行回表查询</strong>。一个索引包含（覆盖）所有需要查询字段的值，被称之为&quot;覆盖索引&quot;。</p>
<p>举个简单的例子，假设我们在员工表的年龄上建立了索引，那么当进行<code>select score from student where score &gt; 90</code>的查询时，在索引的叶子节点上，已经包含了score 信息，不会再次进行回表查询。</p>
<h2 id="8-联合索引是什么为什么需要注意联合索引中的顺序"><a class="markdownIt-Anchor" href="#8-联合索引是什么为什么需要注意联合索引中的顺序"></a> 8. 联合索引是什么？为什么需要注意联合索引中的顺序？</h2>
<p>​	MySQL可以使用多个字段同时建立一个索引，叫做<strong>联合索引</strong>。在联合索引中，如果想要命中索引，需要按照<strong>建立索引时的字段顺序</strong>挨个使用，否则无法命中索引。</p>
<p>具体原因为:</p>
<p>​	MySQL<strong>使用索引时需要索引有序</strong>，假设现在建立了<code>&quot;name，age，school&quot;</code>的联合索引，那么索引的排序为: 先按照name排序，如果name相同，则按照age排序，如果age的值也相等，则按照school进行排序。</p>
<p>​	当进行查询时，此时索引仅仅按照name严格有序，因此必须首先使用name字段进行等值查询，之后对于匹配到的列而言，其按照age字段严格有序，此时可以使用age字段用做索引查找，以此类推。因此在建立联合索引的时候应该注意索引列的顺序，一般情况下，将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。</p>
<h2 id="️9-讲一讲mysql的最左前缀原则"><a class="markdownIt-Anchor" href="#️9-讲一讲mysql的最左前缀原则"></a> ⭐️9. 讲一讲MySQL的最左前缀原则?</h2>
<p>​	最左前缀原则就是<strong>最左优先</strong>，在创建多列索引时，要根据业务需求，where子句中<strong>使用最频繁</strong>的一列放在最左边。<br>
​	mysql会一直向右匹配直到<strong>遇到范围查询(&gt;、&lt;、between、like)就停止匹配</strong>，比如a = 1 and b = 2 and c &gt; 3 and d = 4 如果建立(a,b,c,d)顺序的索引，d 是用不到索引的，如果<strong>建立(a,b,d,c)的索引</strong>则都可以用到，a,b,d的顺序可以任意调整。</p>
<ul>
<li>匹配根据<code>创建时</code>的顺序</li>
</ul>
<p>=和in可以乱序，比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序，mysql的查询优化器会帮你优化成索引可以识别的形式。</p>
<h2 id="10-讲一讲前缀索引"><a class="markdownIt-Anchor" href="#10-讲一讲前缀索引"></a> 10. 讲一讲前缀索引？</h2>
<p>​	因为可能我们索引的字段非常长，这既占内存空间，也不利于维护。所以我们就想，如果只把<strong>很长字段的前面的公共部分</strong>作为一个索引，就会产生超级加倍的效果。但是，我们需要注意，order by不支持前缀索引 。</p>
<p>流程是：</p>
<ul>
<li>
<p>先计算完整列的选择性 :<code>select count(distinct col_1)/count(1) from table_1</code></p>
</li>
<li>
<p>再计算不同前缀长度的选择性 :<code>select count(distinct left(col_1,4))/count(1) from table_1</code></p>
</li>
<li>
<p>找到<strong>最优长度</strong>之后，创建前缀索引 :<code>create index idx_front on table_1 (col_1(4))</code></p>
</li>
</ul>
<h2 id="11-了解索引下推吗"><a class="markdownIt-Anchor" href="#11-了解索引下推吗"></a> 11. 了解索引下推吗？</h2>
<p>​	MySQL 5.6引入了<strong>索引下推</strong>优化。默认开启，使用SET optimizer_switch = ‘index_condition_pushdown=off’;可以将其关闭。</p>
<ul>
<li>
<p>有了索引下推优化，可以在<strong>减少回表次数</strong></p>
</li>
<li>
<p>在InnoDB中只针对二级索引有效</p>
</li>
</ul>
<p>官方文档中给的例子和解释如下：</p>
<p>​	在 people_table中有一个二级索引<code>(zipcode，lastname，address)</code>–非聚簇索引，查询是<code>SELECT * FROM people WHERE zipcode=’95054′ AND lastname LIKE ‘%etrunia%’ AND address LIKE ‘%Main Street%’;</code></p>
<ul>
<li>
<p>如果没有使用索引下推技术，则MySQL会通过zipcode=’95054’从存储引擎中查询对应的数据，返回到MySQL服务端，然后MySQL服务端基于lastname LIKE ‘%etrunia%’ and address LIKE ‘%Main Street%’来判断数据是否符合条件</p>
</li>
<li>
<p>如果使用了索引下推技术，则MYSQL<strong>首先</strong>会返回符合zipcode=’95054’的<strong>索引</strong>，然后根据lastname LIKE ‘%etrunia%’ and address LIKE ‘%Main Street%’来<strong>判断索引</strong>是否符合条件。如果符合条件，则根据该索引来定位对应的数据，如果不符合，则直接reject掉。</p>
</li>
</ul>
<h2 id="12-怎么查看mysql语句有没有用到索引"><a class="markdownIt-Anchor" href="#12-怎么查看mysql语句有没有用到索引"></a> 12. 怎么查看MySQL语句有没有用到索引？</h2>
<p>​	通过<strong>explain</strong>，如以下例子：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">EXPLAIN SELECT * FROM employees.titles WHERE emp_no=&#x27;10001&#x27; AND title=&#x27;Senior Engineer&#x27; AND from_date=&#x27;1986-06-26&#x27;; <br></code></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>id</th>
<th>select_type</th>
<th>table</th>
<th>partitions</th>
<th>type</th>
<th>possible_keys</th>
<th>key</th>
<th>key_len</th>
<th>ref</th>
<th>filtered</th>
<th>rows</th>
<th>Extra</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>SIMPLE</td>
<td>titles</td>
<td>null</td>
<td>const</td>
<td>PRIMARY</td>
<td>PRIMARY</td>
<td>59</td>
<td>const,const,const</td>
<td>10</td>
<td>1</td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li>
<p>id：在⼀个⼤的查询语句中每个<strong>SELECT</strong>关键字都对应⼀个唯⼀的id ，如explain select * from s1 where id = (select id from s1 where name = ‘egon1’);第一个select的id是1，第二个select的id是2。有时候会出现两个select，但是id却都是1，这是因为优化器把子查询变成了连接查询</p>
</li>
<li>
<p>select_type：select关键字对应的那个查询的类型: SIMPLE,PRIMARY,SUBQUERY,DEPENDENT,SNION</p>
</li>
<li>
<p>table：每个查询对应的表名 。</p>
</li>
<li>
<p>⭐️type：<code>type</code> 字段比较重要, 它提供了判断查询是否高效的重要依据依据. 通过 <code>type</code> 字段, 我们判断此次查询是 <code>全表扫描</code> 还是 <code>索引扫描</code> 等。</p>
<ul>
<li>如const(主键索引或者唯一二级索引进行等值匹配的情况下)</li>
<li>ref(普通的⼆级索引列与常量进⾏等值匹配)</li>
<li>index(扫描全表索引的覆盖索引) 。</li>
</ul>
<p>通常来说, 不同的 type 类型的性能关系如下:</p>
<ul>
<li><code>ALL &lt; index &lt; range ~ index_merge &lt; ref &lt; eq_ref &lt; const &lt; system</code><br>
<code>ALL</code> 类型因为是全表扫描, 因此在相同的查询条件下, 它是速度最慢的。而 <code>index</code> 类型的查询虽然不是全表扫描, 但是它扫描了所有的索引, 因此比 ALL 类型的稍快.</li>
</ul>
</li>
<li>
<p>possible_key：查询中<strong>可能用到的索引</strong>*(可以把用不到的删掉，降低优化器的优化时间)* 。</p>
</li>
<li>
<p>key：此字段是 MySQL 在当前查询时所<strong>真正使用到的索引</strong>。</p>
</li>
<li>
<p>filtered：查询器预测满足下一次查询条件的百分比 。</p>
</li>
<li>
<p>rows 也是一个重要的字段. MySQL 查询优化器根据统计信息, <u>估算 SQL 要查找到结果集需要扫描读取的数据行数.</u><br>
这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好。</p>
</li>
<li>
<p>extra：表示额外信息，如Using where,Start temporary,End temporary,Using temporary等。</p>
</li>
</ul>
<h2 id="13-为什么官方建议使用自增长主键作为索引"><a class="markdownIt-Anchor" href="#13-为什么官方建议使用自增长主键作为索引"></a> 13. 为什么官方建议使用自增长主键作为索引？</h2>
<p>​	结合B+Tree的特点，<strong>自增主键是连续的</strong>，在插入过程中尽量<strong>减少页分裂</strong>，即使要进行页分裂，也只会分裂很少一部分。并且能减少数据的移动，每次插入都是插入到最后。<strong>总之就是减少分裂和移动的频率。</strong></p>
<p>​	插入连续的数据：</p>
<blockquote>
<p>图片来自：<a target="_blank" rel="noopener" href="https://www.javazhiyin.com/40232.html">https://www.javazhiyin.com/40232.html</a></p>
</blockquote>
<p><img src="/img/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-2.assets/java10-1562726251.gif" srcset="/img/loading.gif" lazyload alt></p>
<p>​	插入非连续的数据：</p>
<p><img src="http://blog-img.coolsen.cn/img/java8-1562726251.gif" srcset="/img/loading.gif" lazyload alt></p>
<h2 id="14-如何创建索引"><a class="markdownIt-Anchor" href="#14-如何创建索引"></a> 14. 如何创建索引？</h2>
<p>创建索引有三种方式。</p>
<p>1、 在执行CREATE TABLE时创建索引</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> user_index2 (<br>	id <span class="hljs-type">INT</span> auto_increment <span class="hljs-keyword">PRIMARY</span> KEY,<br>	first_name <span class="hljs-type">VARCHAR</span> (<span class="hljs-number">16</span>),<br>	last_name <span class="hljs-type">VARCHAR</span> (<span class="hljs-number">16</span>),<br>	id_card <span class="hljs-type">VARCHAR</span> (<span class="hljs-number">18</span>),<br>	information text,<br>    # 索引<br>	KEY name (first_name, last_name),<br>	FULLTEXT KEY (information),<br>	<span class="hljs-keyword">UNIQUE</span> KEY (id_card)<br>);<br></code></pre></td></tr></table></figure>
<p>2、 使用ALTER TABLE命令去增加索引。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> table_name <span class="hljs-keyword">ADD</span> INDEX index_name (column_list);<br></code></pre></td></tr></table></figure>
<p>​	ALTER TABLE用来创建<strong>普通索引</strong>、<strong>UNIQUE索引</strong>或<strong>PRIMARY KEY</strong>索引。</p>
<p>​	其中table_name是要增加索引的表名，column_list指出对哪些列进行索引，多列时各列之间用逗号分隔。</p>
<p>​	索引名index_name可自己命名，缺省时，MySQL将根据第一个索引列赋一个名称。另外，ALTER TABLE允许在单个语句中更改多个表，因此可以在同时创建多个索引。<br>
3、 使用<strong>CREATE INDEX</strong>命令创建。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> INDEX index_name <span class="hljs-keyword">ON</span> table_name (column_list);<br></code></pre></td></tr></table></figure>
<h2 id="15-创建索引时需要注意什么"><a class="markdownIt-Anchor" href="#15-创建索引时需要注意什么"></a> 15. 创建索引时需要注意什么？</h2>
<ul>
<li>非空字段：应该指定列为NOT NULL，除非你想存储NULL。在mysql中，含有空值的列很难进行查询优化，因为它们使得索引、索引的统计信息以及比较运算更加复杂。
<ul>
<li>用0、一个特殊的值或者一个空串代替空值；</li>
</ul>
</li>
<li>取值离散大的字段：（变量各个取值之间的差异程度）的列放到<strong>联合索引的前面</strong>，可以通过count()函数查看字段的差异值，返回值越大说明字段的唯一值越多字段的离散程度高；</li>
<li>索引字段越小越好：数据库的数据存储以页为单位，一页存储的数据越多，一次IO操作获取的数据越大效率越高。</li>
</ul>
<h2 id="16-建索引的原则有哪些"><a class="markdownIt-Anchor" href="#16-建索引的原则有哪些"></a> 16. 建索引的原则有哪些？</h2>
<ul>
<li>
<p>1、最左前缀匹配原则，非常重要的原则，mysql会一直向右匹配直到遇到<strong>范围查询</strong>(&gt;、&lt;、between、like)就停止匹配，比如a = 1 and b = 2 and c &gt; 3 and d = 4 如果建立(a,b,c,d)顺序的索引，d是用不到索引的，如果建立(a,b,d,c)的索引则都可以用到，a,b,d的顺序可以任意调整。</p>
</li>
<li>
<p>2、=和in可以乱序，比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序，mysql的查询优化器会帮你优化成索引可以识别的形式。</p>
</li>
<li>
<p>3、尽量<strong>选择区分度高的列作为索引</strong>，区分度的公式是**<code>count(distinct col)/count(*)</code>**，表示字段不重复的比例，比例越大我们扫描的记录数越少，唯一键的区分度是1，而一些状态、性别字段可能在大数据面前区分度就是0，那可能有人会问，这个比例有什么经验值吗？使用场景不同，这个值也很难确定，一般需要join的字段我们都要求是0.1以上，即平均1条扫描10条记录。</p>
</li>
<li>
<p>4、<strong>索引列不能参与计算</strong>，保持列“干净”，比如<code>from_unixtime(create_time) = ’2014-05-29’</code>就不能使用到索引，原因很简单，b+树中存的都是数据表中的字段值，但进行检索时，需要把所有元素都<u>应用函数</u>才能比较，显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。</p>
</li>
<li>
<p>5、尽量的扩展索引，不要新建索引。比如表中已经有a的索引，现在要加(a,b)的索引，那么只需要修改原来的索引即可。</p>
</li>
</ul>
<h2 id="17-使用索引查询一定能提高查询的性能吗"><a class="markdownIt-Anchor" href="#17-使用索引查询一定能提高查询的性能吗"></a> 17. 使用索引查询一定能提高查询的性能吗？</h2>
<p>​	通常通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。</p>
<p>​	索引需要<strong>空间</strong>来存储，也需要定期维护， 每当有记录在表中增减或索引列被修改时，索引本身也会被修改。 这意味着每条记录的I* NSERT，DELETE，UPDATE将为此多付出4，5 次的磁盘I/O。 因为索引需要额外的存储空间和处理，那些不必要的索引反而会使查询反应时间变慢。</p>
<p>​	使用索引查询不一定能提高查询性能，索引范围查询(INDEX RANGE SCAN)适用于两种情况:</p>
<ul>
<li>基于一个范围的检索，一般查询返回结果集小于表中记录数的30%。</li>
<li>基于非唯一性索引的检索。</li>
</ul>
<h2 id="18-什么情况下不走索引索引失效"><a class="markdownIt-Anchor" href="#18-什么情况下不走索引索引失效"></a> 18. 什么情况下不走索引（索引失效）？</h2>
<h3 id="1-使用-或者-导致索引失效"><a class="markdownIt-Anchor" href="#1-使用-或者-导致索引失效"></a> 1、使用!= 或者 &lt;&gt; 导致索引失效</h3>
<h3 id="2-类型不一致导致的索引失效"><a class="markdownIt-Anchor" href="#2-类型不一致导致的索引失效"></a> 2、类型不一致导致的索引失效</h3>
<h3 id="3-函数导致的索引失效"><a class="markdownIt-Anchor" href="#3-函数导致的索引失效"></a> 3、函数导致的索引失效</h3>
<p>如：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> <span class="hljs-operator">*</span> <span class="hljs-keyword">FROM</span> `<span class="hljs-keyword">user</span>` <span class="hljs-keyword">WHERE</span> <span class="hljs-type">DATE</span>(create_time) <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;2020-09-03&#x27;</span>;<br></code></pre></td></tr></table></figure>
<p>如果使用函数在索引列，这是不走索引的。</p>
<h3 id="4-运算符导致的索引失效"><a class="markdownIt-Anchor" href="#4-运算符导致的索引失效"></a> 4、运算符导致的索引失效</h3>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs n1ql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-symbol">`user`</span> <span class="hljs-keyword">WHERE</span> age - <span class="hljs-number">1</span> = <span class="hljs-number">20</span>;<br></code></pre></td></tr></table></figure>
<p>如果你对列进行了（+，-，*，/，!）, 那么都将不会走索引。</p>
<h3 id="5-or引起的索引失效"><a class="markdownIt-Anchor" href="#5-or引起的索引失效"></a> 5、OR引起的索引失效</h3>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs n1ql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-symbol">`user`</span> <span class="hljs-keyword">WHERE</span> <span class="hljs-symbol">`name`</span> = <span class="hljs-string">&#x27;张三&#x27;</span> <span class="hljs-keyword">OR</span> height = <span class="hljs-string">&#x27;175&#x27;</span>;<br></code></pre></td></tr></table></figure>
<p>​	OR导致索引是在特定情况下的，并不是所有的OR都是使索引失效，如果OR连接的是同一个字段，那么索引不会失效，反之索引失效。</p>
<h3 id="6-模糊搜索导致的索引失效"><a class="markdownIt-Anchor" href="#6-模糊搜索导致的索引失效"></a> 6、<strong>模糊搜索</strong>导致的索引失效</h3>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs n1ql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-symbol">`user`</span> <span class="hljs-keyword">WHERE</span> <span class="hljs-symbol">`name`</span> <span class="hljs-keyword">LIKE</span> <span class="hljs-string">&#x27;%冰&#x27;</span>;<br></code></pre></td></tr></table></figure>
<p>当<code>%</code>放在匹配字段前是不走索引的，放在后面才会走索引。</p>
<h3 id="7-not-in-not-exists导致索引失效"><a class="markdownIt-Anchor" href="#7-not-in-not-exists导致索引失效"></a> 7、<strong>NOT IN、NOT EXISTS</strong>导致索引失效</h3>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/" class="category-chain-item">数据库</a>
  
  
    <span>></span>
    
  <a href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/" class="category-chain-item">MySQL</a>
  
  

  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/%E9%9D%A2%E8%AF%95/">#面试</a>
      
        <a href="/tags/MySQL/">#MySQL</a>
      
        <a href="/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/">#数据库</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>MySQL常见面试题-2</div>
      <div>http://example.com/2022/04/05/20220405-MySQL常见面试题-2/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>叶飞</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年4月5日</div>
        </div>
      
      
      <div class="license-meta-item">
        <div>许可协议</div>
        <div>
          
            
            
              <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
              <span class="hint--top hint--rounded" aria-label="BY - 署名">
                <i class="iconfont icon-by"></i>
              </span>
              </a>
            
          
        </div>
      </div>
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/04/05/20220405-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-3/" title="MySQL常见面试题-3">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">MySQL常见面试题-3</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/04/04/20220404-MySQL%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98-1/" title="MySQL常见面试题-1">
                        <span class="hidden-mobile">MySQL常见面试题-1</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  


  
  









    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
    </div>
  
  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  
      <script>
        if (!window.MathJax) {
          window.MathJax = {
            tex    : {
              inlineMath: { '[+]': [['$', '$']] }
            },
            loader : {
              load: ['ui/lazy']
            },
            options: {
              renderActions: {
                insertedScript: [200, () => {
                  document.querySelectorAll('mjx-container').forEach(node => {
                    let target = node.parentNode;
                    if (target.nodeName.toLowerCase() === 'li') {
                      target.parentNode.classList.add('has-jax');
                    }
                  });
                }, '', false]
              }
            }
          };
        } else {
          MathJax.startup.document.state(0);
          MathJax.texReset();
          MathJax.typeset();
          MathJax.typesetPromise();
        }
      </script>
    

  <script  src="https://lib.baomitu.com/mathjax/3.2.1/es5/tex-mml-chtml.js" ></script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="/js/leancloud.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
